package com.zjmzxfzhl.modules.app.util;

import com.zjmzxfzhl.modules.app.form.Chunk;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 大文件业务实现
 *
 * @author a2417
 * @version 1.0
 * @date 2020/6/29 10:32
 */
@Component
@Slf4j
public class BigFileService {
    @Value("${file.dir}")
    private String dir;
    @Value("${file.urlPrefix}")
    private String urlPrefix;
    public String fileUpload(Chunk chunk,HttpServletResponse response) {

        /**
         * 每一个上传块都会包含如下分块信息：
         * chunkNumber: 当前块的次序，第一个块是 1，注意不是从 0 开始的。
         * totalChunks: 文件被分成块的总数。
         * chunkSize: 分块大小，根据 totalSize 和这个值你就可以计算出总共的块数。注意最后一块的大小可能会比这个要大。
         * currentChunkSize: 当前块的大小，实际大小。
         * totalSize: 文件总大小。
         * identifier: 这个就是每个文件的唯一标示。
         * filename: 文件名。
         * relativePath: 文件夹上传的时候文件的相对路径属性。
         * 一个分块可以被上传多次，当然这肯定不是标准行为，但是在实际上传过程中是可能发生这种事情的，这种重传也是本库的特性之一。
         *
         * 根据响应码认为成功或失败的：
         * 200 文件上传完成
         * 201 文加快上传成功
         * 500 第一块上传失败，取消整个文件上传
         * 507 服务器出错自动重试该文件块上传
         */

        // 存储目录
        String path = "";
        if (chunk.getProjId() == null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            path = "/doc/" + sdf.format(new Date()) + "/" + chunk.getCode();
        } else {
            path =  "/" + chunk.getProjId() + "/" + chunk.getCode();
        }

        String filePath = dir+path;

        File dir=new File(filePath);
        if(!dir.exists()){
            dir.mkdirs();
        }

        File file= new File(filePath, chunk.getName());

        //第一个块,则新建文件
        if(chunk.getIndex()==1 && !file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                response.setStatus(500);
                return "exception:createFileException";
            }
        }

        //进行写文件操作
        try(
                //将块文件写入文件中
                InputStream fos=chunk.getFile().getInputStream();
                RandomAccessFile raf =new RandomAccessFile(file,"rw")
        ) {
            int len=-1;
            byte[] buffer=new byte[1024];
            raf.seek((chunk.getIndex()-1)*1024*1024*1);
            while((len=fos.read(buffer))!=-1){
                raf.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
            if(chunk.getIndex()==1) {
                file.delete();
            }
            response.setStatus(507);
            return "exception:writeFileException";
        }
        if(chunk.getIndex().equals(chunk.getTotal())){
            response.setStatus(200);
            // TODO 向数据库中保存上传信息
            System.out.println(urlPrefix+path+"/"+chunk.getName());
            return urlPrefix+path+"/"+chunk.getName();
            //return "https://img0.baidu.com/it/u=2907774689,2490288737&fm=253&fmt=auto&app=120&f=JPEG?w=545&h=500";
        }else {
            response.setStatus(201);
            System.out.println(urlPrefix+path+"/"+chunk.getName());
            return urlPrefix+path+"/"+chunk.getName();
            //return "https://img0.baidu.com/it/u=2907774689,2490288737&fm=253&fmt=auto&app=120&f=JPEG?w=545&h=500";
        }
    }

}
